<template>
  <el-card>
    <!-- 
      type="primary" 蓝色经典按钮
      icon 渲染的图标
    -->
    <el-button type="primary" :icon="Plus" @click="showSaveOrUpdateTrademark()"
      >添加品牌</el-button
    >
    <!-- 
      data 表格要渲染的数据
      border 带边框
     -->
    <el-table
      v-loading="loading"
      :data="trademarkList"
      border
      class="trademark-table"
    >
      <!-- 
        el-table-column 列
          prop  这一列决定要渲染data数据中哪个字段
          label 列的标题
          width 列的宽度
          type="index" 显示从1开始的序号
          align="center" 文字居中
      -->
      <el-table-column label="序号" type="index" width="60" align="center" />
      <el-table-column prop="tmName" label="品牌名称" />
      <el-table-column label="品牌Logo">
        <!-- 
          当前列会通过作用域插槽传递数据，
            row    当前要渲染数据（整行数据）
            $index 当前要渲染数据的下标
         -->
        <template v-slot="{ row }">
          <img :src="row.logoUrl" :alt="row.tmName" class="trademark-img" />
        </template>
      </el-table-column>
      <el-table-column label="操作" width="150">
        <!--
          列要渲染的内容有两种方式指定：
            1. prop="xxx" 将来数据xxx就会渲染到当前列
            2. 默认插槽，插槽的内容就是列要渲染的内容
              当默认插槽和prop="xxx"同时指定时，默认插槽优先级更高，默认插槽生效
        -->
        <template v-slot="{ row }">
          <el-button
            type="warning"
            :icon="Edit"
            size="small"
            @click="showSaveOrUpdateTrademark(row)"
          />
          <el-button
            type="danger"
            :icon="Delete"
            size="small"
            @click="showRemoveTrademark(row)"
          />
        </template>
      </el-table-column>
    </el-table>

    <!-- 
      分页器组件
        currentPage 当前页码
        page-size   每页条数
        page-sizes  每页条数的选项
        small 是否渲染小的组件
        layout 要加载的组件
          total, 总数
          sizes, 每页条数的选项
          prev,  前翻页
          pager, 显示页码
          next,  后翻页
          jumper 快速跳转至某页
          -> 让内容去右边
        total 总数
        @size-change 当page-size发生变化触发事件
          先更新page-size的值，再触发的事件
          因为v-model双向绑定的属性，所以当前组件的pageSize的值也更新了，然后触发的事件
        @current-change 当currentPage发生变化触发事件
    -->
    <el-pagination
      v-model:currentPage="currentPage"
      v-model:page-size="pageSize"
      :page-sizes="[3, 6, 9]"
      :small="true"
      layout="prev, pager, next, jumper, ->, sizes, total"
      :total="total"
      @size-change="getTrademarkList"
      @current-change="getTrademarkList"
    />

    <el-dialog
      v-model="visible"
      :title="`${trademarkFormData.id ? '修改' : '添加'}品牌`"
    >
      <!-- 
        label-width label文字的宽度
        ref="trademarkFormRef" 
          获取el-form组件的实例对象，通过实例对象，来调用表单组件的一些方法
            validate      整个表单触发表单校验
            resetFields   清空表单
            clearValidate 清空表单校验结果

        :model="trademarkFormData"
          整个表单数据，将来form表单进行表单校验的时候，从model中读取对应的数据进行校验

        :rules="trademarkFormRules"
          整个表单的表单校验规则
      -->
      <el-form
        label-width="100px"
        ref="trademarkFormRef"
        :model="trademarkFormData"
        :rules="trademarkFormRules"
      >
        <!-- 
          prop指定当前表单项使用哪个表单校验规则
        -->
        <el-form-item label="品牌名称" prop="tmName">
          <!-- v-model收集表单数据 -->
          <el-input
            v-model="trademarkFormData.tmName"
            class="trademark-input"
          />
        </el-form-item>
        <el-form-item label="品牌LOGO" prop="logoUrl">
          <!-- 
            action 上传的服务器地址
              /admin/product/fileUpload 会请求本地开发服务器，本地开发服务器不能处理上传图片请求

              http://gmall-h5-api.atguigu.cn/admin/product/fileUpload 真实开发会产生跨域（现在没有）

              /app-dev/admin/product/fileUpload 走代理服务器，解决跨域

              必须动态读取请求前缀 UPLOAD_URL_PREFIX + '/admin/product/fileUpload'

            show-file-list 是否可以上传多张图片
            on-success 上传成功触发的函数
            before-upload 上传之前触发的函数
          -->
          <el-upload
            class="avatar-uploader"
            :action="UPLOAD_URL_PREFIX + '/admin/product/fileUpload'"
            :show-file-list="false"
            :on-success="handleAvatarSuccess"
            :before-upload="beforeAvatarUpload"
          >
            <img
              v-if="trademarkFormData.logoUrl"
              :src="trademarkFormData.logoUrl"
              class="avatar"
            />
            <el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
            <template #tip>
              <div class="el-upload__tip">
                只能上传jpg/png文件，且不超过200kb
              </div>
            </template>
          </el-upload>
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="visible = false">取消</el-button>
          <el-button type="primary" @click="submitForm">确定</el-button>
        </span>
      </template>
    </el-dialog>
  </el-card>
</template>

<script lang="ts">
export default {
  name: "XTrademark",
};
</script>

<script lang="ts" setup>
import { ref, onMounted, reactive } from "vue";
import { Plus, Edit, Delete } from "@element-plus/icons-vue";
import { ElMessage, ElMessageBox } from "element-plus";
import {
  getTrademarkListApi,
  saveTrademarkApi,
  updateTrademarkApi,
  removeTrademarkApi,
} from "@/api/product/trademark";
import type {
  TrademarkList,
  TrademarkItem,
} from "@/api/product/model/trademarkModel";
import type { UploadProps, FormInstance, FormRules } from "element-plus";

/************************ 删除品牌 *****************************/

const showRemoveTrademark = (row: TrademarkItem) => {
  // https://element-plus.gitee.io/zh-CN/component/message-box.html#%E7%A1%AE%E8%AE%A4%E6%B6%88%E6%81%AF
  ElMessageBox.confirm(`您确认要删除 ${row.tmName} 吗?`, "删除", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning",
  }).then(async () => {
    // 删除
    await removeTrademarkApi(row.id);
    // 提示删除成功
    ElMessage.success("删除品牌成功");
    // 获取最新数据展示
    getTrademarkList();
  });
  // 取消默认隐藏，不需要其他提示
  // .catch(() => {
  //   ElMessage({
  //     type: "info",
  //     message: "Delete canceled",
  //   });
  // });
};

/************************ 表单校验和提交表单 *****************************/

// 获取表单组件实例对象
// FormInstance类型是联合类型，可能有值，可能为undefined
const trademarkFormRef = ref<FormInstance>();

// 定义表单数据
const trademarkFormData = reactive({
  // 定义表单数据的名称，参考将来发送请求，需要的参数名称
  // 品牌名称
  tmName: "",
  // 品牌LOGO
  logoUrl: "",
  // 设置id
  id: 0,
});

// 定义表单校验的规则
const trademarkFormRules = reactive<FormRules>({
  // key 表单校验的规则名称（需要校验的表单数据是啥，规则名称就写啥）
  // value是一个数组，里面包含n个表单校验规则
  tmName: [
    { required: true, message: "请输入品牌名称", trigger: "blur" },
    { min: 2, max: 10, message: "品牌名称长度只能为2-10位", trigger: "blur" },
  ],
  // 上传图片组件没法失去焦点，不需要trigger: "blur"
  logoUrl: [{ required: true, message: "请上传品牌LOGO" }],
});

// 提交表单
const submitForm = () => {
  // 对整个表单进行校验
  // ?. 可选链，前面有值就会执行后面代码，没值就不执行了
  trademarkFormRef.value?.validate(async (valid) => {
    if (valid) {
      // valid为true，代表校验通过，才能发送请求完成功能
      const { tmName, logoUrl, id } = trademarkFormData;

      if (id) {
        // 发送请求，修改品牌
        await updateTrademarkApi({ tmName, logoUrl, id });
      } else {
        // 发送请求，添加品牌
        await saveTrademarkApi(tmName, logoUrl);
      }

      // 提示
      ElMessage.success(`${id ? "修改" : "添加"}品牌成功`);
      // 将对话框隐藏
      visible.value = false;
      // 再次获取数据展示
      getTrademarkList();
    }
    // 校验失败，进行错误提示，自动提示错误
  });
};
/**************************** 对话框显示&隐藏 ********************************/

// 添加品牌对话框显示&隐藏的标识
const visible = ref(false);

// 显示添加品牌
// const showSaveTrademark = () => {
//   visible.value = true;
//   trademarkFormData.tmName = "";
//   trademarkFormData.logoUrl = "";
//   trademarkFormData.id = 0; // 这样才会显示添加的title
//   trademarkFormRef.value?.clearValidate();
// };

// 显示修改品牌
// const showUpdateTrademark = (row: TrademarkItem) => {
//   // 显示对话框
//   visible.value = true;
//   // 给表单赋值
//   trademarkFormData.tmName = row.tmName;
//   trademarkFormData.logoUrl = row.logoUrl;
//   trademarkFormData.id = row.id; // 将来发送更新请求，需要id
//   trademarkFormRef.value?.clearValidate();
// };

// 合并上述两个函数
const showSaveOrUpdateTrademark = (
  row: TrademarkItem = { tmName: "", logoUrl: "", id: 0 }
) => {
  // 显示对话框
  visible.value = true;
  // 给表单赋值
  trademarkFormData.tmName = row.tmName;
  trademarkFormData.logoUrl = row.logoUrl;
  trademarkFormData.id = row.id; // 将来发送更新请求，需要id
  // 清空表单校验结果
  trademarkFormRef.value?.clearValidate();
};

/**************************** 上传图片功能 ********************************/

// 请求前缀
const UPLOAD_URL_PREFIX = import.meta.env.VITE_API_URL;

// const imageUrl = ref("");

// 上传成功触发的函数
const handleAvatarSuccess: UploadProps["onSuccess"] = (response) => {
  // response 上传服务器响应的内容
  trademarkFormData.logoUrl = response.data; // response.data才是上传成功的图片地址

  // 上传成功，清空图片表单失败信息
  trademarkFormRef.value?.clearValidate(["logoUrl"]);
};

// 上传之前触发的函数：限制图片的大小和类型
const beforeAvatarUpload: UploadProps["beforeUpload"] = (rawFile) => {
  // rawFile 上传的文件
  // rawFile.type 上传的文件类型
  /*
    http协议规定的文件格式：mineType
      js    application/js
      css   text/css
      html  text/html
      json  application/json
      图片  image/jpeg image/jpg image/png image/gif
  */
  // 定义合法的图片类型数组
  const imageTypes = ["image/jpeg", "image/jpg", "image/png"];

  if (!imageTypes.includes(rawFile.type)) {
    ElMessage.error("上传的图片必须是jpg或png格式!");
    return false;
    // rawFile.size 上传的文件大小
  } else if (rawFile.size / 1024 > 200) {
    ElMessage.error("上传的图片不能超过200kb!");
    return false;
  }

  return true;
};

/************************* 品牌列表数据分页展示 **************************/

// 当前页码
const currentPage = ref(1);
// 每页条数
const pageSize = ref(3);
// 总数
const total = ref(0);
// 品牌列表数据
const trademarkList = ref<TrademarkList>([]);
// 是否loading
const loading = ref(false);

// 封装一个用来发送请求的函数
const getTrademarkList = async () => {
  loading.value = true;
  const res = await getTrademarkListApi(currentPage.value, pageSize.value);
  // 更新数据
  trademarkList.value = res.records;
  total.value = res.total;
  loading.value = false;
  ElMessage.success("获取品牌分页列表成功");
};

// 当pageSize发送变化触发的回调
// const handleSizeChange = (newPageSize: number) => {
//   // pageSize.value = newPageSize;
//   getTrademarkList();
// };
// 当currentPage发送变化触发的回调
// const handleCurrentChange = (newCurrentPage: number) => {
//   // currentPage.value = newCurrentPage;
//   getTrademarkList();
// };

// 一上来请求数据
// onMounted(() => {
//   getTrademarkList();
// });
onMounted(getTrademarkList);
</script>

<style scoped>
.trademark-table {
  margin: 10px 0;
}
.trademark-img {
  width: 150px;
  height: 100px;
}
.trademark-input {
  width: 70%;
}
</style>

<style>
/* 因为要upload组件样式，所以要定义全局样式或深度选择器 */
.avatar-uploader .avatar {
  width: 178px;
  height: 178px;
  display: block;
}

.avatar-uploader .el-upload {
  border: 1px dashed var(--el-border-color);
  border-radius: 6px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  transition: var(--el-transition-duration-fast);
}

.avatar-uploader .el-upload:hover {
  border-color: var(--el-color-primary);
}

.el-icon.avatar-uploader-icon {
  font-size: 28px;
  color: #8c939d;
  width: 178px;
  height: 178px;
  text-align: center;
}
</style>
